module Utils where

import Data.Graph.Inductive.Tree(UGr)
import Data.Graph.Inductive.Graph(nodes,edges,delNode,Node)
import CPUTime(cpuTimePrecision)
import Random(getStdRandom, randomR)

removeAll :: [Node] -> UGr -> UGr
removeAll what from = foldl (\graph x -> delNode x graph) from what

isThereNoEdge :: UGr -> Bool
isThereNoEdge graph =
	case edges graph of
		[] -> True
		otherwise -> False

--check if it is cover
isCover :: [Node] -> UGr -> Bool
isCover proposition = isThereNoEdge . removeAll proposition

--merge 2 sorted lists with rule
--fun must return negative if element from second list follows by element from first
merge :: (Num a, Ord a) => (t -> t -> a) -> [t] -> [t] -> [t]
merge fun l1 l2 =
	case (l1,l2) of
		 ([],l) -> l
 		 (l,[]) -> l
		 (x:xs,y:ys) -> if (fun x y) <= 0 
						then x : (merge fun xs (y:ys))
						else y : (merge fun (x:xs) ys)

--give us half of the list
halfOfList :: [a] -> [a]
halfOfList list = take ((length list) `div` 2) list

--get random elem from list
getRandomElem :: Int -> Int -> UGr -> [Node] -> Node
getRandomElem numPop numChild graph cover = list !! pointer
	where
		numVertecies = length $ nodes graph
		list = nodes $ removeAll cover graph
		pointer = (numPop * numVertecies + numChild) `mod` (length list)

--another variant to get random element through standart library
pick :: [a] -> IO a
pick []     = undefined
pick [x]    = do return x
pick a = do 
	r <- getStdRandom (randomR (1, length a)) 
	return $ a !! (r-1)

--the rule of addition in sorted list
--the biggest element is first
addIntoList :: [[a]] -> [a] -> [[a]]
addIntoList list elem = 
	case list of
		[] -> (elem:[])
		(x:xs) -> if (length x < length elem)
					then (x:(addIntoList xs elem))
					else (elem:x:xs)
